Продолжается подписка на наши издания! Вы не забыли подписаться?

Теория и практика Java: Повышение эффективности тестирования

Автор: Брайан Гетц
Quiotix
Опубликовано: 04.07.2007

Пишите не просто тестовые программы, а детекторы ошибок

В наши дни большинство коллективов разработчиков считает юнит-тестирование неотъемлемой частью процесса разработки. Фреймворки, подобные JUnit, настолько облегчили тестирование, что даже, если оно нам не нравится, все равно возникает желание написать несколько тестов для некоторых частей нашего кода. Но юнит-тесты могут проверить только часть кода, а сам тестовый код, как правило, редко применяется повторно – тесты, созданные вчера для компонента A, вряд ли подойдут для проверки компонента B, разве что в качестве примера.

Стандартный сценарий юнит-тестирования

Что вы делаете в первую очередь при обнаружении ошибки? Вы можете просто ее исправить, но в конечном итоге такой подход может быть не самым эффективным. В большинстве программистских фирм процесс выглядит примерно так:

Хотя данный подход и является более трудоемким по сравнению с простым исправлением ошибки, однако он более практичен, так как дает больше уверенности, не только в том, что ошибка устранена, потому что вы выполнили тестирование, но и в том, что ошибка не вернется вновь, потому что тест является частью вашей регрессионной тестовой последовательности. Исправлению, сохраненному в системе контроля версий, соответствует запись в системе отслеживания ошибок, описывающая ошибку и способ ее устранения.

Можно также подумать о том, из-за чего была сделана ошибка, и поискать другие места, где могла быть сделана та же самая ошибка. Затем, если вы найдете ту же самую ошибку в другом месте, то можно также исправить ее и сохранить исходный код в систему контроля версий. Однако главным уязвимым местом юнит-тестирования как инструмента для управления качеством является то, что каждый отдельный тест может проверять только одну часть кода. Поскольку тесты приходится писать для каждого компонента и каждого потенциального вида сбоя, то написание достаточного числа юнит-тестов для проверки большого продукта может быть в высшей степени затратным с точки зрения средств и времени.

Экономика контроля качества

Несмотря на то, что тесты являются эффективным средством контроля качества, всем известно, что даже обширного набора тестов недостаточно для обнаружения всех ошибок в сложном программном продукте. В действительности "обнаружение всех ошибок" в любой нетривиальной программе является невыполнимой задачей. В НАСА на одного разработчика приходится 20 тестировщиков – гораздо больше, чем любая коммерческая структура может себе позволить потратить на контроль качества - однако даже при таких условиях в программном обеспечении есть недочеты. Следовательно, целью всего процесса контроля качества должно быть не обнаружение всех ошибок, так как это невозможно, а повышение уверенности в том, что код работает, до максимально возможного при данных ресурсах уровня.

Эффективный контроль качества предполагает планирование распределения доступных ресурсов между доступными методиками контроля качества для максимального увеличения надежности. Набор тестов с большим охватом, так же, как и детальный просмотр кода, увеличивают нашу уверенность в том, что код работает. Конечно, лучше реализовывать обе методики, чем только одну из них, потому что первая может обнаружить те ошибки, которые, вероятно, были пропущены второй, и наоборот. Кроме того, потратить X долларов на тестирование и Y долларов на просмотр кода эффективнее, чем потратить X+Y долларов на любое из средств в отдельности.

Применение статического анализа

Статический анализ – это процесс анализа кода без его запуска, который очень похож на те процессы, которые происходят в нашей голове во время просмотра кода или на то, что делают IDE, когда помечают сомнительные конструкции. Статический анализ – это метод, который разумно было бы добавить в набор методик контроля качества, так как это еще одна хорошая методика обнаружения ошибок, которые могут быть пропущены другими (например, тестированием и просмотром кода). Кроме того, статический анализ относительно дешев: в отличие от юнит-тестов, которые приходится писать заново для каждого проверяемого класса, инструментальные средства статического анализа можно использовать для любой части кода.

FindBugs является open source-инструментом статического анализа, в котором содержатся детекторы для большого количества распространенных ошибок. Возможно, это кого-то удивит, но он зачастую находит "тупые" ошибки даже в хорошо проверенном программном обеспечении – ошибки, которые обычно пропускают юнит-тесты и эксперты по просмотру кода. FindBugs также позволяет вам создавать детекторы для новых образцов ошибок в виде расширений, то есть, если стандартный набор детекторов не выполняет поставленной задачи, вы можете легко написать свой собственный детектор. Именно возможность расширения превращает FindBugs в мощное инструментальное средство контроля качества благодаря тому, что как только вы обнаруживаете новые типы ошибок, вы можете написать для них новые детекторы и проверить весь нужный код.

Основная ценность статического анализа – это проверка информации на выходе и определение, что из найденного является ошибками, а что – ложной тревогой. Управление количеством ложных срабатываний является неотъемлемой частью написания хорошего инструмента для анализа или детектора ошибок; при настройке детекторов в центральном модуле FindBugs ставилась цель допускать не более 50 процентов ложных срабатываний, чтобы проверка результатов была не слишком проблематичной (сравните этот порог с инструментами, подобными lint для C, которые обычно порождают так много ложных сообщений об ошибках, что их почти невозможно использовать).

Переход на уровень вверх

Листинг 1. Пример типичной ошибки – путаница между фабричным методом и изменяемым методом

Пример детектора ошибок

Листинг 2. Код, показывающий шаблон ошибки, для которой необходимо создать детектор
Листинг 3. Байт-код для кода, приведенного в листинге 2
Листинг 4. Детектор ошибок для нахождения вызовов System.gc()

Упаковка детекторов в модули расширения

Листинг 5. Дескриптор развертывания для детектора ошибок, приведенного в примере.
Листинг 6. Файл ресурсов для детектора ошибок, приведенного в примере.

Заключение

Статический анализ и пользовательские детекторы ошибок могут быть очень выгодным методом улучшения качества программного обеспечения. Создавая детектор для известного шаблона ошибки, мы можем проверить на наличие данной ошибки не только текущий код конкретного проекта, но и любой проект, имеющийся или будущий. Дополнительные усилия, затрачиваемые на создание детектора ошибок, в будущем окупятся с лихвой.


Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав.
........................
"С полным содержанием данной статьи можно ознакомиться в печатной версии журнала"

Copyright © 1994-2016 ООО "К-Пресс"